/* ******************************************************************
 * This file is part of the escal project and distributed under the
 * terms of the GNU General Public License Version 3
 * Copyright (C) 2008 Epocher (xijiaosdq@gmail.com)
 * See COPYING file for licensing information.
 *******************************************************************/
#include "Python.h"
#include "scanner_dialog.h"
#include "escal.h"
#include "escal_settings.h"
#include "scanner_thread.h"
#include <QFileDialog>
#include <QRadioButton>
#include <QMessageBox>

using namespace Escal;

static ScannerDialog *dialog;

ScannerDialog::ScannerDialog(QWidget *parent)
	:QDialog(parent), scannerThread(this)
{
	setupUi(this);
	
	urlListModel = new ScannerUrlListModel(this);
	urlListView->setModel(urlListModel);
	connect(this, SIGNAL(getUrl(QString)),
			urlListModel, SLOT(addUrl(QString)));
	scannerUrlListDelegate = new ScannerUrlListDelegate(this);
	urlListView->setItemDelegate(scannerUrlListDelegate);
	urlListView->setRootIsDecorated(false);
	urlListView->setEditTriggers(QAbstractItemView::AllEditTriggers);
	//urlListView->setEditTriggers(QAbstractItemView::AnyKeyPressed);
	setModal(false);
	dirDialog = new QFileDialog(this);
        dirDialog->setFileMode(QFileDialog::DirectoryOnly);
	dirDialog->setAcceptMode(QFileDialog::AcceptOpen);
	scriptDialog = new QFileDialog(this);
        scriptDialog->setFileMode(QFileDialog::ExistingFile);
	scriptDialog->setAcceptMode(QFileDialog::AcceptOpen);
	scriptDialog->setNameFilters(QStringList("Python Files *.py"));
	connect(urlInput, SIGNAL(textChanged ( const QString &)),
	    this, SLOT(urlChanged(const QString &)));
	connect(clearButton, SIGNAL(clicked()),
		urlListModel, SLOT(clear()));

	dialog = this;
	Py_Initialize();
	connect(&scannerThread, SIGNAL(finished()),
			this, SLOT(switchToStopped()));
	init_py_mod();
}

void ScannerDialog::reset(){
	urlListModel->clear();
	keepRunning = false;
	folderInput->setText(settings->value("Folder/DownloadFolderList")
	    .toStringList()[0]);
	QString dirName1 = binaryFilePath;
	{
		int l = binaryFilePath.lastIndexOf("/");
		if(l>0){
			dirName1.resize(l);
			dirName1 += "/plugins";
		}
		else {
			dirName1.resize(0);
			dirName1 += "plugins";
		}
	}
	dirName1 = QDir(dirName1).absoluteFilePath("");
	QString dirName2 = escalHome + "/plugins";
	dirName2 = QDir(dirName2).absoluteFilePath("");
	QStringList scripts;
	QString script;
	QDir pluginDir;
	pluginDir.setNameFilters(QStringList("*.py"));
	pluginDir.setPath(dirName1);
	foreach(script, pluginDir.entryList()){
		scripts << pluginDir.absoluteFilePath(script);
	}
	if(QDir(dirName2).absoluteFilePath("")
			!=QDir(dirName1).absoluteFilePath("")){
		pluginDir.setPath(dirName2);
		foreach(script, pluginDir.entryList()){
			scripts << pluginDir.absoluteFilePath(script);
		}
	}
	pluginDir.setPath("/usr/lib/egear/plugins");
        foreach(script, pluginDir.entryList()){
                scripts << pluginDir.absoluteFilePath(script);
        }
	scriptInput->clear();
	scriptInput->addItems(scripts);
	scriptInput->setCurrentIndex(0);
}

ScannerDialog::~ScannerDialog(){
	Py_Finalize();
};

void ScannerDialog::browseDir(){
    if(dirDialog->exec()){
        QString folderName=dirDialog->selectedFiles()[0];
	folderInput->setText(folderName+"/"+url.host());
    }
};

void ScannerDialog::browseScript(){
    if(scriptDialog->exec()){
        QString fileName=scriptDialog->selectedFiles()[0];
	scriptInput->lineEdit()->setText(fileName);
    }
};

void ScannerDialog::chooseAll(){
	int i;
	for(i=0;i<urlListModel->rowCount();i++){
		urlListModel->setData(urlListModel->index(i, 0), true,
				Qt::CheckStateRole);

	}
};

void ScannerDialog::unchooseAll(){
	int i;
	for(i=0;i<urlListModel->rowCount();i++){
		urlListModel->setData(urlListModel->index(i, 0), false,
				Qt::CheckStateRole);

	}
};

void ScannerDialog::urlChanged(const QString &newUrl){
	url.setUrl(newUrl);
	QString host = url.host();
	if(host==QString()){
		host=newUrl;
		int split = host.indexOf("/");
		if(split > 0){
			host.resize(split);
		}
	}
	folderInput->setText(settings->value("Folder/DownloadFolderList")
	    .toStringList()[0] + "/" + host);
};

void ScannerDialog::putUrl(const QString &newUrl){
	emit getUrl(newUrl);
	qDebug() << "get url:" << newUrl;

};

void ScannerDialog::show(){
	reset();
	QDialog::show();
};

void ScannerDialog::accept(){
	keepRunning = false;
	QStringList urlList = urlListModel->getCheckedUrls();
	QString urlStr;
	QString parentFolder = folderInput->text();
	QString subFolder;
	QString fileName;
	if(keepStructButton->isChecked()){
		foreach(urlStr, urlList){
			QUrl url(urlStr);
			fileName = url.path();
			subFolder = fileName;
			int split = fileName.lastIndexOf("/");
			subFolder.resize(split);
			fileName.remove(0, split+1);
			if(fileName==QString()){
				fileName = "index.html";
			}
			emit newTask(url, parentFolder + "/" + subFolder,
				fileName);
		}
	}
	else{
		foreach(urlStr, urlList){
			QUrl url(urlStr);
			fileName = url.path();
			int split = fileName.lastIndexOf("/");
			fileName.remove(0, split+1);
			if(fileName==QString()){
				fileName = "index.html";
			}
			emit newTask(url, parentFolder + subFolder,
				fileName);
		}
	}
	QDialog::accept();
};

void ScannerDialog::reject(){
	keepRunning = false;
	QDialog::reject();
};

void ScannerDialog::startScan(){
	if(keepRunning==false){
		switchToRunning();
	}
	else{
		switchToStopped();
	}
};

void ScannerDialog::switchToRunning(){
	scanButton->setText(tr("Cancel"));
	urlInput->setEnabled(false);
	scriptInput->setEnabled(false);
	browseScriptButton->setEnabled(false);
	depthSpinBox->setEnabled(false);
	chooseAllButton->setEnabled(false);
	unchooseAllButton->setEnabled(false);
	if(urlInput->text().simplified()==QString()){
		QMessageBox::warning(this, tr("warning"),
			tr("the url inputted is empty!"));
		return;
	}
	if(scannerThread.isRunning()){
		scannerThread.terminate();
	}
	scannerThread.setScriptPath(scriptInput->lineEdit()->text());
	keepRunning=true;
	scannerThread.start();
}
void ScannerDialog::switchToStopped(){
	keepRunning=false;
	scanButton->setText(tr("Scan"));
	urlInput->setEnabled(true);
	scriptInput->setEnabled(true);
	browseScriptButton->setEnabled(true);
	depthSpinBox->setEnabled(true);
	chooseAllButton->setEnabled(true);
	unchooseAllButton->setEnabled(true);

}

PyObject *ScannerDialog::putUrl_py(PyObject *self, PyObject *args){
	char *url;
	if (!PyArg_ParseTuple(args, "s", &url))
		return NULL;
	qDebug() << url;
	QString urlStr = QString::fromUtf8(url);
	qDebug() << urlStr;
	dialog->putUrl(urlStr);
	Py_RETURN_NONE;
};

PyObject *ScannerDialog::getDest_py(PyObject *self, PyObject *args){
	QString url = dialog->urlInput->text();
	PyObject *obj = Py_BuildValue("s", url.toUtf8().constData());
	return obj;
};

PyObject *ScannerDialog::keepRunning_py(PyObject *self, PyObject *args){
	if(dialog->isKeepRunning()){
		Py_RETURN_TRUE;
	}
	else{
		Py_RETURN_FALSE;
	}
};	

PyObject *ScannerDialog::getDepth_py(PyObject *self, PyObject *args){
	int depth = dialog->depthSpinBox->value();
	PyObject *obj = Py_BuildValue("i", depth);
	return obj;
};

static PyMethodDef DialogMethods[] = {
	{"putUrl", ScannerDialog::putUrl_py, METH_VARARGS},
	{"keepRunning", ScannerDialog::keepRunning_py, METH_NOARGS},
	{"getDest", ScannerDialog::getDest_py, METH_NOARGS},
	{"getDepth", ScannerDialog::getDepth_py, METH_NOARGS},
	{NULL, NULL}
};

void ScannerDialog::init_py_mod(){
	(void) Py_InitModule("dialog", DialogMethods);
};

// ********************* ScannerUrlListModel ******************************

ScannerUrlListModel::ScannerUrlListModel(QObject *parent)
	:QAbstractItemModel(parent)
{
	columnHeaders << tr("url");
}
int ScannerUrlListModel::columnCount(const QModelIndex &parent) const{
	return columnHeaders.size(); 
};

int ScannerUrlListModel::rowCount(const QModelIndex &parent) const{
	return urlList.size();
};

Qt::ItemFlags ScannerUrlListModel::flags(const QModelIndex &index) const{
	if (!index.isValid()) return 0;
		return Qt::ItemIsEnabled | Qt::ItemIsSelectable | 
			Qt::ItemIsEditable ;
};

QVariant ScannerUrlListModel::headerData(int column,
		Qt::Orientation orientation, int role) const
{	
	if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
		return columnHeaders[column];
	return QVariant();
};		

QModelIndex ScannerUrlListModel::index(int row, int column,
		const QModelIndex &parent) const
{
	if(parent == QModelIndex())
		return createIndex (row, column);
	else
		return QModelIndex();
};

QModelIndex ScannerUrlListModel::parent(const QModelIndex &index) const{
	return QModelIndex();
};

QVariant ScannerUrlListModel::data(const QModelIndex& index, int role) const{
	if (!index.isValid())
		return QVariant();

	if (role == Qt::DisplayRole && index.column()==0)
		return urlList[index.row()];

	if(role == Qt::CheckStateRole && index.column()==0){
		return checkList[index.row()];
	}
	return QVariant();
}

bool ScannerUrlListModel::setData(const QModelIndex & index,
		const QVariant &value, int role){
	if (!index.isValid()) return false;
	if(role == Qt::CheckStateRole && index.column()==0){
		checkList[index.row()] = value.toBool();
		emit dataChanged (index, index);
		return true;
	}
	return false;
};

void ScannerUrlListModel::addUrl(const QString &url) {
	int row = urlList.size();
	beginInsertRows(QModelIndex(), row, row);
	urlList.append(url);
	checkList.resize(row+1);
	checkList[row]=true;
	endInsertRows();
};

QStringList ScannerUrlListModel::getCheckedUrls(){
	QStringList urls;
	int i;
	for(i=0;i<urlList.size();i++){
		if(checkList[i]){
			urls << urlList[i];
		}
	}
	return urls;
};

void ScannerUrlListModel::clear(){
	checkList.clear();
	urlList.clear();
	reset();
}

// ******************* ScannerUrlListDelegate *****************************
void ScannerUrlListDelegate::paint(QPainter *painter, 
	const QStyleOptionViewItem &option,
	const QModelIndex &index ) const
{
	if (index.column() != 0) {
		QStyledItemDelegate::paint(painter, option, index);
		return;
	}

	// Set up a QStyleOptionProgressBar to precisely mimic the
	// environment of a progress bar.
	QStyleOptionButton buttonStateOption;
	if(index.model()->data(index, Qt::CheckStateRole).toBool()){
		buttonStateOption.state = QStyle::State_On;
	}
	else{
		buttonStateOption.state = QStyle::State_Off;
	}
	buttonStateOption.direction = QApplication::layoutDirection();
	buttonStateOption.rect = option.rect;
	buttonStateOption.fontMetrics = QApplication::fontMetrics();
	buttonStateOption.text = index.model()->data(index).toString();
	
	// Draw the progress bar onto the view.
	QApplication::style()->drawControl(
			QStyle::CE_RadioButton, 
			&buttonStateOption, painter);
};

QWidget *ScannerUrlListDelegate::createEditor(QWidget *parent,
	const QStyleOptionViewItem &option, const QModelIndex & index ) const{
	QRadioButton *radioButton = new QRadioButton(parent);
	return radioButton;
};

void ScannerUrlListDelegate::setEditorData(QWidget *editor,
			 const QModelIndex &index) const
{
	bool value = index.model()->data(index,
			Qt::CheckStateRole).toBool();
	QRadioButton *radioButton = static_cast<QRadioButton*>(editor);
	radioButton->setChecked(value);
};

void ScannerUrlListDelegate::setModelData(QWidget *editor,
	QAbstractItemModel *model,const QModelIndex & index ) const{
	QRadioButton *radioButton = static_cast<QRadioButton*>(editor);
	bool value = radioButton->isChecked();
	model->setData(index, value, Qt::CheckStateRole);
};

void ScannerUrlListDelegate::updateEditorGeometry(QWidget *editor,
		const QStyleOptionViewItem &option,
		const QModelIndex &index) const{
	editor->setGeometry(option.rect);
};

